const { Service } = require("egg");

class UserService extends Service {
    /**
     * 根据用户名，查询用户
     * @param {string} username 用户名
     */
    async findByUsername(username) {
        let sql = `select * from user where username = ?`;
        let params = [username];
        let res = await this.app.mysql.query(sql, params);
        return res[0];
    }

    /**
     * 添加用户
     * @param {object} param0 用户信息字段
     */
    async add({ username, password, nickname, rid }) {
        // 查询用户是否存在
        let user = await this.findByUsername(username);
        if (user) {
            this.ctx.cast(404, "用户不存在");
        }

        // 初始化事务
        const conn = await this.app.mysql.beginTransaction();

        // 执行多表操作
        try {
            // 生成一个用户id
            const uid = this.ctx.helper.uuid();

            // 向用户表中，添加用户
            await conn.query(
                "insert into user (id, username, password, nickname) values (?, ?, ?, ?)",
                [uid, username, this.ctx.helper.encrypt(password), nickname]
            );

            // 向用户角色表中，添加用户角色关系
            await conn.query(
                "insert into r_user_role (uid, rid) values (?, ?)",
                [uid, rid]
            );

            // 没有报错，提交事务
            await conn.commit();

            // 出错了，回滚事务
        } catch (error) {
            // 回滚事务
            await conn.rollback();
            // 抛出异常
            this.ctx.cast(500, error.message);
        }
    }

    /**
     * 用户列表
     */
    async readList() {
        let sql = `
            select
                u.*, r.id as rid, r.name as rname
            from user as u
                join r_user_role as rur on u.id = rur.uid
                join role as r on rur.rid = r.id
        `;
        let res = await this.app.mysql.query(sql);
        return res;
    }

    /**
     * 修改用户信息
     * @param {number} id 用户id
     * @param {object} user 要修改的信息
     */
    async update(id, user) {
        // 没有要修改的内容
        if (!user || user.length === 0) {
            return;
        }
        // 如果修改用户名，则不能重复
        if (user.username) {
            const record = await this.findByUsername(user.username);
            if (record) {
                this.ctx.cast(403, 该用户名已存在);
            }
        }

        // 开启事务，因为修改身份需要涉及到两张表
        const conn = await this.app.mysql.beginTransaction();

        try {
            // 如果需要修改身份信息
            if (user.rid) {
                await conn.query(
                    "update r_user_role set rid = ? where uid = ?",
                    [user.rid, id]
                );
                // 因为下面会拼接字符串，而 rid 不在 user 表中，所以要删除
                delete user.rid;
            }

            // 按需修改 user 字段
            let sql = "update user set ";
            let params = [];
            Object.entries(user).forEach((item, index, arr) => {
                sql +=
                    arr.length - 1 !== index
                        ? ` ${item[0]} = ?, `
                        : ` ${item[0]} = ? `;

                if (item[0] === "password") {
                    item[1] = this.ctx.helper.encrypt(item[1]);
                }
                params.push(item[1]);
            });
            sql += " where id = ? ";
            params.push(id);
            await conn.query(sql, params);

            // 提交事务
            await conn.commit();
        } catch (error) {
            // 回滚事务
            await conn.rollback();
            // 抛出异常
            this.ctx.cast(500, error.message);
        }
    }
}

module.exports = UserService;
